<?

require_once('config.php');

require_once('functions/general.php');
require_once('sql/sql_offender.php');
require_once('sql/sql_offense.php');
require_once('sql/sql_area.php');

define('TPL_INCIDENT_VIEW', 'incident_view.tpl');
define('TPL_INCIDENT_FORM', 'incident_form.tpl');

define('VIEW_LATEST', 'latest');
define('VIEW_AREA', 'area');
define('VIEW_OFFENSE', 'offense');
define('VIEW_USER', 'user');


class Incident {
    private $smarty;
    private $sql_area;
    private $sql_offense;
    private $sql_offender;
    private $sql_incident;

    public function __construct($smarty, $mysql_link) {
        $this->smarty = $smarty;
        $this->sql_area = new Sql_area($mysql_link);
        $this->sql_offense = new Sql_offense($mysql_link);
        $this->sql_offender = new Sql_offender($mysql_link);
        $this->sql_incident = new Sql_incident($mysql_link);

    }

    public function show_new_incident_form() {
        $smarty = $this->smarty;
        $smarty->assign('areas',    $this->sql_area->get_areas_with_pos());
        $smarty->assign('offenses', $this->sql_offense->get_offenses());

        return TPL_INCIDENT_FORM;
    }

    
    /**
     * Add new incident.
     * Returns true on succs, false on errors.
     */
    public function add_new_incident($data, $logged_in) {
        # Extract input
        list(	$time, $offender, $area, 
                $offense, $lon, $lat, $comment, $captcha ) 
            = array_extract_vars($data, array(
                        'date_time', 'offender', 'area', 
                        'offense', 'lon', 'lat', 'comment', 'captcha'));

        # validate
        $errors = $this->validate_input(
            $logged_in, $captcha, $offense, $time, array($lon, $lat));
        if ($errors) {
            $this->smarty->assign('error_msgs', $this->_error_msgs());
            $this->smarty->assign('errors', $errors);
            $this->smarty->assign('post', $data);
            return false;
        }

        # Process input
        $time = ceil($time / 1000); # ms since 1970. We want seconds.

        $offender_id = null; 
        $offender = strip_tags(strtoupper($offender));
        if ($offender) {
            $offender_id = $this->sql_offender->insert_offender($offender);
        }

        # Add to db
        $incident_id = $this->sql_incident
            ->insert_incident($area, $time, 
                    $offense, $offender_id, 
                    $lon, $lat, $comment);

        $this->smarty->assign('incident_id', $incident_id);

        # show user message.
        $this->smarty->assign('incident_added', true);
        
        return true;
    }


            

    public function show_incidents($view, $filter, $offset = 0) {
        global $CONFIG;
        $per_page = $CONFIG['incidents_per_page'];

        $incidents = null;
        $total_count = null;

        switch ($view) {
            case VIEW_LATEST:
                list($incidents, $total_count) = $this->sql_incident->get_last(
                        $offset, $per_page, OPT_GET_COUNT);
                break;

            case VIEW_AREA:
                list($incidents, $total_count) = 
                    $this->show_area($offset, $per_page, $filter['area']);
                break;

            case VIEW_OFFENSE:
                list($incidents, $total_count) = 
                    $this->show_offense($offset, $per_page, $filter['offense']);
                break;

            case VIEW_USER:
                list($incidents, $total_count) = 
                    $this->show_user($offset, $per_page, $filter['user']);
                break;

           default:
                print("Unknown view"); 
                assert(0);
        }

        assert(is_array($incidents));
        assert(is_numeric($total_count));
       
        $this->smarty->assign('view', $view);
        $this->smarty->assign('incidents', $incidents);
        $this->tpl_assign_navigation($offset, $total_count);
        return TPL_INCIDENT_VIEW;
    }

    /**
     * Assigns variables needed to navigate results
     * to template.
    */
    private function tpl_assign_navigation($offset, $total_count) {
        global $CONFIG;
        $per_page = $CONFIG['incidents_per_page'];

        # do we have next/previus page?
        $next_page = null;
        $prev_page = null;
        if ($offset + $per_page < $total_count) {
            $next_page = 1 + floor(($offset + $per_page) / $per_page);
        }
        
        if ($offset > 0) {
            $prev_offset = $offset - $per_page;
            if ($prev_offset > 0) {
                $prev_page = 1 + ceil($prev_offset / $per_page);
            }
            else {
                $prev_page = 1;
            }
        }

        # pages
        $pages_total = 1 + floor($total_count / $per_page);
        if ($offset)
            $at_page = 1 + floor($offset / $per_page);
        else $at_page = 1;

        # Assign to tpl
        $this->smarty->assign('incidents_total', $total_count);
        $this->smarty->assign('next_page', $next_page);
        $this->smarty->assign('prev_page', $prev_page);
        
        $this->smarty->assign('page', $at_page);
        $this->smarty->assign('pages_total', $pages_total);
        
    }

    private function validate_input($logged_in, $captcha, $offense, $time, $coords) {

        $errors = array();
        if (!$logged_in) {
            if (!$captcha) 
                $errors[] = "captcha_missing";
            else if ((strtolower($captcha) != $_SESSION['captcha'])) {
                $errors[] = "captcha_wrong";
            }
        }

        if (!$offense)
            $errors[] = "offense_missing";

        list($lon, $lat) = $coords;
        if (!$lon or !$lat)
            $errors[] = "coordinates_missing";

        if (!$time) {
            $errors[] = "time_missing";
        }
        else {
            if (ceil($time / 1000) > time())
                $errors[] = "time_in_feature";
        }

        return (count($errors)) ? $errors : null;
    }

    private function _error_msgs() {
        # TODO: Move error_msgs array decleration to template
        # when smarty devs stop arguing and start supporting array assignment.
        return array(
                'captcha_missing'     => "Du må skrive inn teksten i 
                bildet til å vise at du er et menneske.",
                'captcha_wrong'       => "Teksten du skrev i menneskesjekken 
                stemte ikke med bildet.",
                'offense_missing'     => "Du må velge synd.",
                'coordinates_missing' => "Du må legge til ett punkt på kartet hvor hendelsen skjedde.",
                'time_in_feature'     => "Tidspunktet du la til er i fremtiden.",
                'time_missing'        => "Du må velge tidspunkt."
                );
    }

    /**
     * Helper method for show_incidents
     */
    private function show_area($offset, $per_page, $filter) {
        global $CONFIG;
        $area_filter = $filter
            ?  $filter : $CONFIG['default_area_filter'];

        # Fetch SQL data.
        list($incidents, $total_count) = $this->sql_incident->get_by_area(
                $offset, $per_page, $area_filter, OPT_GET_COUNT);
        $area_list = $this->sql_area->get_areas();

        # Assign
        $this->smarty->assign('area_list', $area_list);
        $this->smarty->assign('area_filter', $area_filter);
        $this->smarty->assign('area_unspecified', AREA_FILTER_UNSPECIFIED);
        
        return array($incidents, $total_count);
    }


    private function show_offense($offset, $per_page, $filter) {
        global $CONFIG;
        if (!$filter)
            $filter = $CONFIG['default_offense_filter'];
        list($incidents, $total_count) = $this->sql_incident->get_by_offense(
                $offset, $per_page, $filter, OPT_GET_COUNT);
        $offense_list = $this->sql_offense->get_offenses();

        assert(strlen($filter) > 0);
        $this->smarty->assign(array(
            'offense_list' => $offense_list,
            'offense_filter' => $filter
        ));

        return array($incidents, $total_count);
    }

    private function show_user($offset, $per_page, $filter) {
        global $CONFIG;
        list($incidents, $total_count) = $this->sql_incident->get_by_user(
                $offset, $per_page, $filter, OPT_GET_COUNT);
        $user_list = $this->sql_incident->get_users();
        $this->smarty->assign(array(
            'user_list' => $user_list,
            'user_filter' => $filter
        ));
        
        return array($incidents, $total_count);
    }

}

?>
